﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using PasteBuilder.Models;
//using PasteBuilder.Models.TemplateModels;
//using RazorEngine.Configuration;
//using RazorEngine.Templating;
//using Engine = RazorEngine.Engine;
using File = System.IO.File;
using ProjectItem = EnvDTE.ProjectItem;
using Task = System.Threading.Tasks.Task;
//using Template = PasteBuilder.Templates.Template;

namespace PasteBuilder
{
    /// <summary>
    /// Command handler
    /// </summary>
    internal sealed class BuilderCommand
    {
        public static DTE2 _dte;

        /// <summary>
        /// Command ID.
        /// </summary>
        public const int CommandId = 0x0100;

        /// <summary>
        /// Command menu group (command set GUID).
        /// </summary>
        public static readonly Guid CommandSet = new Guid("19BBD6DA-E935-4F19-8CFB-BD4D0ACBD69A");

        /// <summary>
        /// VS Package that provides this command, not null.
        /// </summary>
        private readonly AsyncPackage package;

        /// <summary>
        /// Initializes a new instance of the <see cref="BuilderCommand"/> class.
        /// Adds our command handlers for menu (commands must exist in the command table file)
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        /// <param name="commandService">Command service to add command to, not null.</param>
        private BuilderCommand(AsyncPackage package, OleMenuCommandService commandService)
        {
            //InitRazorEngine();
            this.package = package ?? throw new ArgumentNullException(nameof(package));
            commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

            var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem = new MenuCommand(this.Execute, menuCommandID);
            commandService.AddCommand(menuItem);

            //using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PDF2PPT.Aspose.Total.lic"))
            //{
            //    string content = new StreamReader(stream).ReadToEnd();
            //}



            //ExecuteLog
            //var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem2 = new MenuCommand(this.ExecuteLog, new CommandID(CommandSet, 0x0101));
            commandService.AddCommand(menuItem2);

        }

        //private void InitRazorEngine()
        //{
        //    var config = new TemplateServiceConfiguration
        //    {
        //        TemplateManager = new EmbeddedResourceTemplateManager(typeof(Template))
        //    };
        //    config.CompilerServiceFactory = new RazorEngine.Roslyn.RoslynCompilerServiceFactory();
        //    config.Language = RazorEngine.Language.CSharp;

        //    Engine.Razor = RazorEngineService.Create(config);
        //}

        /// <summary>
        /// Gets the instance of the command.
        /// </summary>
        public static BuilderCommand Instance
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the service provider from the owner package.
        /// </summary>
        private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
        {
            get
            {
                return this.package;
            }
        }

        /// <summary>
        /// Initializes the singleton instance of the command.
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        public static async Task InitializeAsync(AsyncPackage package, DTE2 dte)
        {
            // Switch to the main thread - the call to AddCommand in AbpCustomCommand's constructor requires
            // the UI thread.
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

            _dte = dte;
            OleMenuCommandService commandService = await package.GetServiceAsync((typeof(IMenuCommandService))) as OleMenuCommandService;
            Instance = new BuilderCommand(package, commandService);
        }


        private List<string> _enumList;

        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private void Execute(object sender, EventArgs e)
        {
            ThreadHelper.ThrowIfNotOnUIThread();



            var _resultTitle = new System.Text.StringBuilder();
            _resultTitle.AppendLine("【PasteBuilder】");
            try
            {
                _deletelog();

                //模板内容
                TemplateModel _templatebody = new TemplateModel();

                //WriteTextLog("Read Assembly File:"+ Assembly.GetExecutingAssembly().GetName().Name);

                var _assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

                // PasteBuilder.template.add.txt
                using (Stream _stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{_assemblyName}.template.dto.txt"))
                {
                    var _filesize = new byte[_stream.Length];
                    _stream.Read(_filesize, 0, (int)_stream.Length);
                    var _str = Encoding.UTF8.GetString(_filesize);
                    _templatebody.dtobody = _str;
                }

                using (Stream _stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{_assemblyName}.template.index.html"))
                {
                    var _filesize = new byte[_stream.Length];
                    _stream.Read(_filesize, 0, (int)_stream.Length);
                    var _str = Encoding.UTF8.GetString(_filesize);
                    _templatebody.indexbody = _str;
                }

                using (Stream _stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{_assemblyName}.template.server.txt"))
                {
                    var _filesize = new byte[_stream.Length];
                    _stream.Read(_filesize, 0, (int)_stream.Length);
                    var _str = Encoding.UTF8.GetString(_filesize);
                    _templatebody.serverbody = _str;
                }

                using (Stream _stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{_assemblyName}.template.view.html"))
                {
                    var _filesize = new byte[_stream.Length];
                    _stream.Read(_filesize, 0, (int)_stream.Length);
                    var _str = Encoding.UTF8.GetString(_filesize);
                    _templatebody.viewbody = _str;
                }

                using (Stream _stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{_assemblyName}.template.helper.txt"))
                {
                    var _filesize = new byte[_stream.Length];
                    _stream.Read(_filesize, 0, (int)_stream.Length);
                    var _str = Encoding.UTF8.GetString(_filesize);
                    _templatebody.helperbody = _str;
                }

                _enumList = new List<string>();

                if (_dte.SelectedItems.Count > 0)
                {
                    foreach (var ione in _dte.SelectedItems)
                    {
                        //这里为啥要获取1呢
                        SelectedItem selectedItem = (SelectedItem)ione;
                        ProjectItem selectProjectItem = selectedItem.ProjectItem;
                        if (selectProjectItem != null)
                        {
                            _ReadEnumList(selectProjectItem.FileCodeModel.CodeElements, _enumList);
                        }
                    }

                    toLog("Enum get count:" + _enumList.Count + " " + string.Join("-", _enumList.ToArray()));

                    foreach (var ione in _dte.SelectedItems)
                    {
                        //这里为啥要获取1呢
                        SelectedItem selectedItem = (SelectedItem)ione;

                        ProjectItem selectProjectItem = selectedItem.ProjectItem;

                        if (selectProjectItem != null)
                        {
                            //前端工程源码目录
                            //string frontBaseUrl = "";

                            var codes = new List<CodeClass>();
                            _ReadClassList(selectProjectItem.FileCodeModel.CodeElements, codes);
                            //var codes = GetListClass(selectProjectItem.FileCodeModel.CodeElements);

                            if (codes != null && codes.Count() > 0)
                            {
                                foreach (var codeClass in codes)
                                {
                                    if (codeClass != null)
                                    {
                                        #region 获取出基础信息
                                        //获取当前点击的类所在的项目
                                        Project topProject = selectProjectItem.ContainingProject;

                                        toLog("当前点击的类所在的项目名称为:" + topProject.Name);
                                        //当前类在当前项目中的目录结构
                                        /**
                                         * 项目所在文件夹
                                         **/
                                        string dirPath = GetSelectFileDirPath(topProject, selectProjectItem);
                                        toLog("项目所在文件夹为:" + dirPath);

                                        //当前类命名空间
                                        string namespaceStr = selectProjectItem.FileCodeModel.CodeElements.OfType<CodeNamespace>().First().FullName;
                                        toLog("类的命名空间:" + dirPath);
                                        //当前项目根命名空间
                                        string applicationStr = "";
                                        if (!string.IsNullOrEmpty(namespaceStr))
                                        {
                                            if (namespaceStr.IndexOf(".") > 0)
                                            {
                                                //applicationStr = namespaceStr.Substring(0, namespaceStr.IndexOf("."));
                                                if (topProject.Name.EndsWith(".Domain"))
                                                {
                                                    applicationStr = topProject.Name.Replace(".Domain", "");
                                                }
                                                //去除最后一个
                                            }
                                            else
                                            {
                                                applicationStr = namespaceStr;
                                            }
                                        }
                                        toLog("项目命名空间:" + applicationStr);
                                        toLog(selectProjectItem.FileCodeModel != null ? "selectProjectItem.FileCodeModel not null" : "selectProjectItem.FileCodeModel is null");
                                        //当前项目类名
                                        string className = codeClass.Name;
                                        //当前类中文名 [Display(Name = "供应商")]
                                        string classCnName = "";
                                        //当前类说明 [Description("品牌信息")]
                                        string classDescription = "";
                                        //默认的Entity为int
                                        string defaultbasetype = "int";//uint 有些数据库为long类型了
                                                                       //类的注释文本，请不要换行
                                        string displayStr = "";
                                        //获取类的中文名称和说明
                                        foreach (CodeAttribute classAttribute in codeClass.Attributes)
                                        {
                                            switch (classAttribute.Name)
                                            {
                                                case "Description":
                                                    classDescription = classAttribute.Value;
                                                    break;
                                                case "DisplayName":
                                                    classCnName = classAttribute.Value;
                                                    break;
                                                case "CType":
                                                    defaultbasetype = classAttribute.Value;
                                                    break;
                                                    //case "Comment"://这个是数据库注释
                                                    //    displayStr = classAttribute.Value.Replace("\"","");
                                                    //    break;
                                            }
                                        }

                                        //读取他的基类 默认为int
                                        var bases = codeClass.Bases;
                                        if (bases != null)
                                        {
                                            foreach (CodeElement _base in bases)
                                            {
                                                var _full = _base.FullName;
                                                switch (_full)
                                                {
                                                    case "Volo.Abp.Domain.Entities.Entity<System.Int64>":
                                                        {
                                                            defaultbasetype = "long";
                                                        }
                                                        break;
                                                    case "Volo.Abp.Domain.Entities.Entity<System.String>":
                                                        {
                                                            defaultbasetype = "string";
                                                        }
                                                        break;
                                                    case "Volo.Abp.Domain.Entities.Entity<System.Guid>":
                                                        {
                                                            defaultbasetype = "Guid";
                                                        }
                                                        break;
                                                }
                                            }
                                        }

                                        var summary = "";
                                        if (!String.IsNullOrEmpty(codeClass.DocComment))
                                        {
                                            summary = codeClass.DocComment.Replace("<doc>", "").Replace("</doc>", "").Replace("<summary>", "").Replace("</summary>", "").Replace("\r", "").Replace("\n", "").Replace("，", ",").Trim();
                                            displayStr = summary;
                                            if (!String.IsNullOrEmpty(summary))
                                            {
                                                if (String.IsNullOrEmpty(classCnName))
                                                {
                                                    if (summary.Contains(" ") || summary.Contains(","))
                                                    {
                                                        var spacehead = summary.Split(' ')[0];
                                                        var douhead = summary.Split(',')[0];
                                                        if (douhead.Length < spacehead.Length)
                                                        {
                                                            classCnName = douhead;
                                                        }
                                                        else
                                                        {
                                                            classCnName = spacehead;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        classCnName = displayStr;
                                                    }
                                                }
                                            }
                                        }

                                        toLog("当前类的属性获取完成");


                                        //获取当前解决方案里面的项目列表
                                        var finditems = GetSolutionProjects(_dte.Solution);
                                        List<ProjectItem> solutionProjectItems = finditems.Item1;
                                        List<Project> projects = finditems.Item2;

                                        #endregion
                                        #region 流程实现
                                        TapClassModel dtoModel = null;


                                        //自定义模板信息

                                        #region 读取文件模板 .Domain server.html index.html view.html

                                        var _prodomainitems = ReadProjectItem(solutionProjectItems, projects, $"{applicationStr}.Domain");

                                        if (_prodomainitems != null)
                                        {
                                            var _templatepath = _prodomainitems.Item("template");
                                            if (_templatepath != null)
                                            {
                                                foreach (ProjectItem item in _templatepath.ProjectItems)
                                                {
                                                    toLog($"读取模板文件{item.Name}");
                                                    #region 读取模板信息
                                                    if (item.Name.EndsWith("server.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.serverbody = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("dto.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.dtobody = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("index.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.indexbody = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("view.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.viewbody = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("add.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.addbody = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("edit.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.editbody = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("vueedit.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.vueedit = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("vueadd.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.vueadd = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("vueindex.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.vueindex = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    if (item.Name.EndsWith("vueview.html"))
                                                    {
                                                        var filefullname = item.FileNames[0];
                                                        if (!String.IsNullOrEmpty(filefullname))
                                                        {
                                                            if (System.IO.File.Exists(filefullname))
                                                            {
                                                                _templatebody.vueview = System.IO.File.ReadAllText(filefullname);
                                                            }
                                                        }
                                                    }
                                                    #endregion
                                                }
                                            }
                                            else
                                            {
                                                toLog($"{applicationStr}.Domain/template is null!");
                                            }
                                        }
                                        else
                                        {
                                            toLog($"{applicationStr}.Domain Project is null!");
                                        }

                                        #endregion

                                        var _pcontracts = _finddiritem($"{applicationStr}.Application.Contracts", dirPath, solutionProjectItems, projects);
                                        if (_pcontracts != null)
                                        {
                                            dtoModel = GetDtoModel(applicationStr, className, classCnName, classDescription, dirPath, codeClass);
                                            dtoModel.CnName = classCnName;
                                            dtoModel.EntityType = defaultbasetype;
                                            dtoModel.DisplayStr = displayStr;
                                            CreateDtoFile(dtoModel, _pcontracts, _templatebody);
                                        }
                                        else
                                        {
                                            _resultTitle.AppendLine($"项目{applicationStr}.Application.Contracts 未找到");
                                        }

                                        var _proefcitems = ReadProjectItem(solutionProjectItems, projects, $"{applicationStr}.EntityFrameworkCore");
                                        if (_proefcitems != null)
                                        {
                                            var _tempfolder = _proefcitems.Item("EntityFrameworkCore");
                                            if (_tempfolder != null)
                                            {
                                                SetDbSetToDbContext(_tempfolder.ProjectItems, applicationStr, className, dtoModel);
                                            }
                                        }

                                        #region application模块
                                        ProjectItem _serverdirproject = null;
                                        var _proservices = ReadProjectItem(solutionProjectItems, projects, $"{applicationStr}.Application");
                                        if (_proservices != null)
                                        {
                                            SetMapper(_proservices, className, classCnName);
                                            _serverdirproject = _proservices.Item(dirPath);
                                            if (_serverdirproject == null)
                                            {
                                                _serverdirproject = _proservices.AddFolder(dirPath);
                                            }
                                            var _helperdir = _proservices.Item("pastehelper");
                                            if (_helperdir == null)
                                            {
                                                _helperdir = _proservices.AddFolder("pastehelper");
                                            }
                                            if (_helperdir != null)
                                            {
                                                var __helper = _helperdir.ProjectItems.Item("PasteBuilderHelper.cs");
                                                if (__helper == null)
                                                {
                                                    if (!String.IsNullOrEmpty(_templatebody.helperbody))
                                                    {
                                                        AddFileToProjectItem(_helperdir, buildFileContentByTemplate(dtoModel, _templatebody.helperbody), $"PasteBuilderHelper.cs");
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            _resultTitle.AppendLine($"项目{applicationStr}.Application 未找到");
                                        }
                                        if (_serverdirproject != null)
                                        {
                                            CreateServiceFile(dtoModel, _serverdirproject, _templatebody);
                                        }
                                        else
                                        {
                                            _resultTitle.AppendLine($"项目{applicationStr}.Application/{dirPath} 未找到并创建失败！");
                                        }
                                        #endregion

                                        var _prohost = ReadProjectItem(solutionProjectItems, projects, $"{applicationStr}.HttpApi.Host");
                                        if (_prohost != null)
                                        {
                                            _BuildHtml(_prohost, dtoModel, _templatebody);
                                        }
                                        else
                                        {
                                            _resultTitle.AppendLine($"项目{applicationStr}.HttpApi.Host 未找到");
                                        }
                                        _resultTitle.AppendLine("代码生成成功！");
                                        _resultTitle.AppendLine("https://www.pastecode.cn/");
                                        #endregion
                                    }
                                }
                            }
                            else
                            {
                                toLog("没有遍历到class");
                            }
                        }
                        else
                        {
                            toLog("没有选择的项目");
                        }
                    }
                }
                else
                {
                    toLog("没有选择的项目！");
                }
            }
            catch (Exception exl)
            {
                _resultTitle.AppendLine(exl.Message);
            }
            VsShellUtilities.ShowMessageBox(this.package, _resultTitle.ToString(), "PasteBuilder", OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
        }

        /// <summary>
        /// 从解决方案找找到某一个项目，可能是有文件夹
        /// </summary>
        /// <param name="solutionProjectItems"></param>
        /// <param name="projects"></param>
        /// <param name="proname">xxx.EntityFrameworkCore</param>
        /// <returns></returns>
        private ProjectItems ReadProjectItem(List<ProjectItem> solutionProjectItems, List<Project> projects, string proname)
        {
            ProjectItem _proefc = solutionProjectItems.Find(t => t.Name == proname);
            if (_proefc != null)
            {
                if (_proefc.SubProject != null)
                {
                    return _proefc.SubProject.ProjectItems;
                }
            }
            else
            {
                var tempproject = projects.Find(t => t.Name == proname);
                if (tempproject != null)
                {
                    return tempproject.ProjectItems;
                }
            }
            return null;
        }

        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private void ExecuteLog(object sender, EventArgs e)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var _resultTitle = new System.Text.StringBuilder();
            _resultTitle.AppendLine("【PasteCodeBuilder】");

            _deletelog();

            _enumList = new List<string>();
            string message = "";

            if (_dte.SelectedItems.Count > 0)
            {
                foreach (var ione in _dte.SelectedItems)
                {
                    //这里为啥要获取1呢
                    SelectedItem selectedItem = (SelectedItem)ione;
                    ProjectItem selectProjectItem = selectedItem.ProjectItem;
                    if (selectProjectItem != null)
                    {
                        _ReadEnumList(selectProjectItem.FileCodeModel.CodeElements, _enumList);
                    }
                }

                toLog("Enum get count:" + _enumList.Count + " " + string.Join("-", _enumList.ToArray()));

                foreach (var ione in _dte.SelectedItems)
                {
                    //这里为啥要获取1呢
                    SelectedItem selectedItem = (SelectedItem)ione;

                    ProjectItem selectProjectItem = selectedItem.ProjectItem;

                    if (selectProjectItem != null)
                    {
                        //前端工程源码目录
                        //string frontBaseUrl = "";

                        var codes = new List<CodeClass>();
                        _ReadClassList(selectProjectItem.FileCodeModel.CodeElements, codes);
                        //var codes = GetListClass(selectProjectItem.FileCodeModel.CodeElements);

                        if (codes != null && codes.Count() > 0)
                        {
                            foreach (var codeClass in codes)
                            {
                                if (codeClass != null)
                                {
                                    #region 获取出基础信息
                                    //获取当前点击的类所在的项目
                                    Project topProject = selectProjectItem.ContainingProject;

                                    toLog("当前点击的类所在的项目名称为:" + topProject.Name);
                                    //当前类在当前项目中的目录结构
                                    /**
                                     * 项目所在文件夹
                                     **/
                                    string dirPath = GetSelectFileDirPath(topProject, selectProjectItem);
                                    toLog("项目所在文件夹为:" + dirPath);

                                    //当前类命名空间
                                    string namespaceStr = selectProjectItem.FileCodeModel.CodeElements.OfType<CodeNamespace>().First().FullName;
                                    toLog("类的命名空间:" + dirPath);
                                    //当前项目根命名空间
                                    string applicationStr = "";
                                    if (!string.IsNullOrEmpty(namespaceStr))
                                    {
                                        if (namespaceStr.IndexOf(".") > 0)
                                        {
                                            //applicationStr = namespaceStr.Substring(0, namespaceStr.IndexOf("."));
                                            if (topProject.Name.EndsWith(".Domain"))
                                            {
                                                applicationStr = topProject.Name.Replace(".Domain", "");
                                            }
                                            //去除最后一个
                                        }
                                        else
                                        {
                                            applicationStr = namespaceStr;
                                        }
                                    }
                                    toLog("项目命名空间:" + applicationStr);
                                    toLog(selectProjectItem.FileCodeModel != null ? "selectProjectItem.FileCodeModel not null" : "selectProjectItem.FileCodeModel is null");
                                    //当前项目类名
                                    string className = codeClass.Name;
                                    //当前类中文名 [Display(Name = "供应商")]
                                    string classCnName = "";
                                    //当前类说明 [Description("品牌信息")]
                                    string classDescription = "";
                                    //默认的Entity为int
                                    string defaultbasetype = "int";//uint 有些数据库为long类型了
                                    //类的注释文本，请不要换行
                                    string displayStr = "";
                                    //获取类的中文名称和说明
                                    foreach (CodeAttribute classAttribute in codeClass.Attributes)
                                    {
                                        switch (classAttribute.Name)
                                        {
                                            //case "Display":
                                            //    if (!string.IsNullOrEmpty(classAttribute.Value))
                                            //    {
                                            //        string displayStrtemp = classAttribute.Value.Trim();
                                            //        foreach (var displayValueStr in displayStrtemp.Split(','))
                                            //        {
                                            //            if (!string.IsNullOrEmpty(displayValueStr))
                                            //            {
                                            //                if (displayValueStr.Split('=')[0].Trim() == "Name")
                                            //                {
                                            //                    classCnName = displayValueStr.Split('=')[1].Trim().Replace("\"", "");
                                            //                }
                                            //            }
                                            //        }
                                            //    }
                                            //    break;
                                            case "Description":
                                                classDescription = classAttribute.Value;
                                                break;
                                            case "DisplayName":
                                                classCnName = classAttribute.Value;
                                                break;
                                            case "CType":
                                                defaultbasetype = classAttribute.Value;
                                                break;
                                                //case "Comment"://这个是数据库注释
                                                //    displayStr = classAttribute.Value.Replace("\"","");
                                                //    break;
                                        }
                                    }


                                    var summary = "";
                                    if (!String.IsNullOrEmpty(codeClass.DocComment))
                                    {
                                        summary = codeClass.DocComment.Replace("<doc>", "").Replace("</doc>", "").Replace("<summary>", "").Replace("</summary>", "").Replace("\r", "").Replace("\n", "").Replace("，", ",").Trim();
                                        displayStr = summary;
                                        if (!String.IsNullOrEmpty(summary))
                                        {
                                            if (String.IsNullOrEmpty(classCnName))
                                            {
                                                if (summary.Contains(" ") || summary.Contains(","))
                                                {
                                                    var spacehead = summary.Split(' ')[0];
                                                    var douhead = summary.Split(',')[0];
                                                    if (douhead.Length < spacehead.Length)
                                                    {
                                                        classCnName = douhead;
                                                    }
                                                    else
                                                    {
                                                        classCnName = spacehead;
                                                    }
                                                }
                                                else
                                                {
                                                    classCnName = displayStr;
                                                }
                                            }
                                        }
                                    }

                                    //if (String.IsNullOrEmpty(classCnName))
                                    //{
                                    //    classCnName = displayStr;
                                    //}

                                    //displayStr = codeClass.DocComment.Trim().Replace("<doc>", "").Replace("</doc>", "").Replace("<summary>", "").Replace("</summary>", "").Replace("\r", "").Replace("\n", "");
                                    //if (!String.IsNullOrEmpty(displayStr))
                                    //{
                                    //    displayStr = ToShortName(displayStr);
                                    //}
                                    toLog("当前类的属性获取完成");


                                    //获取当前解决方案里面的项目列表
                                    var finditems = GetSolutionProjects(_dte.Solution);
                                    List<ProjectItem> solutionProjectItems = finditems.Item1;
                                    List<Project> projects = finditems.Item2;

                                    #endregion
                                    #region 流程实现
                                    TapClassModel dtoModel = null;

                                    //构建基础数据模型
                                    dtoModel = GetDtoModel(applicationStr, className, classCnName, classDescription, dirPath, codeClass);
                                    dtoModel.CnName = classCnName;
                                    dtoModel.EntityType = defaultbasetype;
                                    dtoModel.DisplayStr = displayStr;

                                    ProjectItem entityFrameworkProjectItem = solutionProjectItems.Find(t => t.Name == applicationStr + ".EntityFrameworkCore");
                                    if (entityFrameworkProjectItem != null)
                                    {
                                        var applicationNewFolder = entityFrameworkProjectItem.SubProject.ProjectItems.Item("EntityFrameworkCore");
                                        if (applicationNewFolder != null)
                                        {
                                            if (applicationNewFolder.ProjectItems != null)
                                            {
                                                SetDbSetToDbContext(applicationNewFolder.ProjectItems, applicationStr, className, dtoModel);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        var tempproject = projects.Find(t => t.Name == $"{applicationStr}.EntityFrameworkCore");
                                        if (tempproject != null)
                                        {

                                            var _tempfolder = tempproject.ProjectItems.Item("EntityFrameworkCore");
                                            if (_tempfolder != null)
                                            {
                                                SetDbSetToDbContext(_tempfolder.ProjectItems, applicationStr, className, dtoModel);
                                            }
                                        }
                                        else
                                        {
                                            _resultTitle.AppendLine($"项目{applicationStr}.EntityFrameworkCore 未找到");
                                        }
                                    }
                                    //ProjectItem applicationProjectItem = solutionProjectItems.Find(t => t.Name == applicationStr + ".Application");
                                    //if (applicationProjectItem != null)
                                    //{
                                    //    SetMapper(applicationProjectItem, className, classCnName);
                                    //    var _tempfolder = applicationProjectItem.SubProject.ProjectItems.Item(dirPath);
                                    //    if (_tempfolder == null)
                                    //    {
                                    //        _tempfolder = applicationProjectItem.SubProject.ProjectItems.AddFolder(dirPath);
                                    //    }

                                    //    CreateServiceFile(dtoModel, _tempfolder);
                                    //}
                                    //else
                                    //{
                                    //    var tempproject = projects.Find(t => t.Name == $"{applicationStr}.Application");
                                    //    if (tempproject != null)
                                    //    {
                                    //        SetMapper(tempproject.ProjectItems, className, classCnName);
                                    //        var applicationNewFolder = tempproject.ProjectItems.Item(dirPath);
                                    //        if (applicationNewFolder == null)
                                    //        {
                                    //            applicationNewFolder = tempproject.ProjectItems.AddFolder(dirPath);
                                    //        }
                                    //        CreateServiceFile(dtoModel, applicationNewFolder);
                                    //    }
                                    //    else
                                    //    {
                                    //        _resultTitle.AppendLine($"项目{applicationStr}.Application 未找到");
                                    //    }
                                    //}

                                    //ProjectItem hostproject = solutionProjectItems.Find(t => t.Name == applicationStr + ".HttpApi.Host");
                                    //if (hostproject != null)
                                    //{
                                    //    _BuildHtml(hostproject.SubProject.ProjectItems, dtoModel, className);
                                    //}
                                    //else
                                    //{
                                    //    var tempproject = projects.Find(t => t.Name == $"{applicationStr}.HttpApi.Host");
                                    //    if (tempproject != null)
                                    //    {
                                    //        _BuildHtml(tempproject.ProjectItems, dtoModel, className);
                                    //    }
                                    //    else
                                    //    {
                                    //        _resultTitle.AppendLine($"项目{applicationStr}.HttpApi.Host 未找到");
                                    //    }
                                    //}
                                    message = "代码生成成功！--- soft.pastecode.cn ---";
                                    #endregion
                                }
                            }
                        }
                        else
                        {
                            toLog("没有遍历到class");
                        }
                    }
                    else
                    {
                        toLog("没有选择的项目");
                    }
                }
            }
            else
            {
                toLog("没有选择的项目！");
            }
            VsShellUtilities.ShowMessageBox(this.package, message, _resultTitle.ToString(), OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="projectitems"></param>
        /// <param name="dtoModel"></param>
        /// <param name="className"></param>
        private void _BuildHtml(ProjectItems projectitems, TapClassModel dtoModel, TemplateModel template = null)
        {
            var _rootproject = projectitems.Item("wwwroot");
            if (_rootproject == null)
            {
                _rootproject = projectitems.AddFolder("wwwroot");
            }
            if (_rootproject != null)
            {
                var _manageproject = _rootproject.ProjectItems.Item("manage");
                if (_manageproject == null)
                {
                    _manageproject = _rootproject.ProjectItems.AddFolder("manage");
                }
                if (_manageproject != null)
                {
                    var _dirproject = _manageproject.ProjectItems.Item(dtoModel.Name.ToLower());
                    if (_dirproject == null)
                    {
                        _dirproject = _manageproject.ProjectItems.AddFolder(dtoModel.Name.ToLower());
                    }
                    if (_dirproject != null)
                    {
                        if (!String.IsNullOrEmpty(template.indexbody))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.indexbody), "index.html");
                        }
                        else
                        {
                            toLog($"按照内置模型创建文件{dtoModel.Name.ToLower()}/index.html");
                            _AddItemDtoFile("htmlindex", $"index.html", dtoModel, _dirproject);
                        }

                        if (!String.IsNullOrEmpty(template.viewbody))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.viewbody), "view.html");
                        }
                        else
                        {
                            _AddItemDtoFile("htmlview", $"view.html", dtoModel, _dirproject);
                        }

                        if (!String.IsNullOrEmpty(template.addbody))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.addbody), "add.html");
                        }

                        if (!String.IsNullOrEmpty(template.editbody))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.editbody), "edit.html");
                        }

                        if (!String.IsNullOrEmpty(template.vueindex))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.vueindex), "index.vue");
                        }

                        if (!String.IsNullOrEmpty(template.vueview))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.vueview), "view.vue");
                        }

                        if (!String.IsNullOrEmpty(template.vueadd))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.vueadd), "add.vue");
                        }

                        if (!String.IsNullOrEmpty(template.vueedit))
                        {
                            AddFileToProjectItem(_dirproject, buildFileContentByTemplate(dtoModel, template.vueedit), "edit.vue");
                        }
                    }
                }
            }
            else
            {
                toLog("文件夹html不存在");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="itemname"></param>
        /// <param name="dirPath"></param>
        /// <param name="projectitems"></param>
        /// <param name="projects"></param>
        /// <returns></returns>
        private ProjectItem _finddiritem(string itemname, string dirPath, List<ProjectItem> projectitems, List<Project> projects)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            ProjectItem _proitem = projectitems.Find(t => t.Name == itemname);
            if (_proitem != null)
            {
                var _prodir = _proitem.SubProject.ProjectItems.Item(dirPath);
                if (_prodir == null)
                {
                    _prodir = _proitem.SubProject.ProjectItems.AddFolder(dirPath);
                }
                return _prodir;
            }
            else
            {
                if (projects != null)
                {
                    var item = projects.Find(t => t.Name == itemname);

                    var _prodir = item.ProjectItems.Item(dirPath);
                    if (_prodir == null)
                    {
                        _prodir = item.ProjectItems.AddFolder(dirPath);
                    }
                    return _prodir;
                }
            }
            return null;
        }

        /// <summary>
        /// 截取名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private string ToShortName(string name)
        {
            if (!String.IsNullOrEmpty(name))
            {
                var cunindex = name.Length - 1;
                if (name.Contains(","))
                {
                    cunindex = Math.Min(name.IndexOf(","), cunindex);
                }
                if (name.Contains("，"))
                {
                    cunindex = Math.Min(name.IndexOf("，"), cunindex);
                }
                if (name.Contains(" "))
                {
                    cunindex = Math.Min(name.IndexOf(" "), cunindex);
                }
                if (cunindex < name.Length - 1)
                {
                    return name.Substring(0, cunindex);
                }
            }
            return name;
        }


        #region 代码生成

        /// <summary>
        /// 获取DtoModel
        /// </summary>
        /// <param name="applicationStr"></param>
        /// <param name="name"></param>
        /// <param name="dirName"></param>
        /// <param name="codeClass"></param>
        /// <returns></returns>
        private TapClassModel GetDtoModel(string applicationStr, string name, string cnName, string description, string dirName, CodeClass codeClass)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var model = new TapClassModel() { Namespace = applicationStr, Name = name, CnName = cnName, Description = description, DirName = dirName.Replace("\\", ".") };
            List<ClassProperty> classProperties = new List<ClassProperty>();
            List<ClassAttribute> classAttributes = null;

            var codeMembers = codeClass.Members;
            foreach (CodeElement codeMember in codeMembers)
            {
                if (codeMember.Kind == vsCMElement.vsCMElementProperty)
                {
                    ClassProperty _classprotry = new ClassProperty();
                    CodeProperty property = codeMember as CodeProperty;
                    _classprotry.Name = property.Name;
                    if (property.Name == "ConcurrencyStamp")
                    {
                        continue;
                    }
                    //WriteTextLog($"{property.Name}==={property.GetPropertyValue("")}");
                    //获取属性类型
                    var propertyType = property.Type;
                    // toLog(string.Format("属性{0} 名称{1} 类型{2} 值{3}","",property.Name, propertyType.ToString(), propertyType.AsFullName));
                    switch (propertyType.TypeKind)
                    {
                        case vsCMTypeRef.vsCMTypeRefString:
                            _classprotry.PropertyType = "string";
                            break;
                        case vsCMTypeRef.vsCMTypeRefInt:
                            _classprotry.PropertyType = "int";
                            break;
                        case vsCMTypeRef.vsCMTypeRefBool:
                            _classprotry.PropertyType = "bool";
                            break;
                        case vsCMTypeRef.vsCMTypeRefDecimal:
                            _classprotry.PropertyType = "decimal";
                            break;
                        case vsCMTypeRef.vsCMTypeRefDouble:
                            _classprotry.PropertyType = "double";
                            break;
                        case vsCMTypeRef.vsCMTypeRefFloat:
                            _classprotry.PropertyType = "float";
                            break;
                        default:
                            _classprotry.PropertyType = propertyType.AsString;
                            break;
                    }
                    _classprotry.PropertyBase = _classprotry.PropertyType;
                    _classprotry.boolOtherModel = false;
                    if (propertyType.TypeKind == vsCMTypeRef.vsCMTypeRefCodeType)
                    {
                        //枚举类型必须为Enum开头,约定

                        //项目里面的其他的模型
                        _classprotry.boolOtherModel = true;
                        if (_classprotry.PropertyType.IndexOf(".") > 0)
                        {
                            if (_classprotry.PropertyType.StartsWith("System."))
                            {
                                _classprotry.boolOtherModel = false;//系统的其他类型，比如时间
                                _classprotry.IsEnumClass = false;
                            }
                        }

                        if (_classprotry.PropertyType.EndsWith("?"))
                        {
                            _classprotry.boolOtherModel = false;
                        }

                        var typeBaseName = FilterOnlyName(_classprotry.PropertyType);

                        //toLog("property.FullName:"+property.Name);

                        if (_enumList.Contains(typeBaseName))
                        {
                            _classprotry.IsEnumClass = true;
                            _classprotry.boolOtherModel = false;
                        }
                        else
                        {
                            if (typeBaseName.StartsWith("Enum"))
                            {
                                _classprotry.IsEnumClass = true;
                                _classprotry.boolOtherModel = false;
                            }
                            else
                            {
                                _classprotry.IsEnumClass = false;
                            }
                        }


                        ////只获取最后的
                        //如何排除枚举类型?
                        //排除List<obje类型>
                        if (!_classprotry.IsEnumClass)
                        {
                            //是List的情况
                            if (_classprotry.PropertyType.EndsWith(">"))
                            {
                                _classprotry.PropertyType = FilterListOnlyName(_classprotry.PropertyType);//.Substring(0, classProperty.PropertyType.Length - 1) + "Dto>";
                            }
                            else
                            {
                                _classprotry.PropertyBase = typeBaseName;
                                if (_classprotry.boolOtherModel)
                                {
                                    _classprotry.PropertyType = typeBaseName + "Dto";
                                }
                                else
                                {//DateTime啥类型啥的
                                    _classprotry.PropertyType = typeBaseName;
                                }
                            }
                        }
                        else
                        {
                            //假设这是一个枚举类型
                            _classprotry.PropertyType = typeBaseName;
                        }
                    }
                    string propertyCnName = "";//属性中文名称
                    classAttributes = new List<ClassAttribute>();
                    //获取属性特性
                    foreach (CodeAttribute itemattribute in property.Attributes)
                    {
                        ClassAttribute _oneattribute = new ClassAttribute();
                        //toLog(codeAttribute.Name);
                        switch (itemattribute.Name)
                        {
                            case "Required":
                                {
                                    _oneattribute.NameValue = "[Required]";
                                    _oneattribute.Name = "Required";
                                    _oneattribute.Value = "true";
                                    _classprotry.Required = true;
                                }
                                break;
                            case "MaxLength":
                                {
                                    int.TryParse(itemattribute.Value, out var imax);
                                    if (imax > 0)
                                    {
                                        _classprotry.MaxLength = imax;
                                    }
                                    _oneattribute.NameValue = "[" + itemattribute.Name + "(" + itemattribute.Value + ")]";
                                    _oneattribute.Name = itemattribute.Name;
                                    _oneattribute.Value = itemattribute.Value;
                                }
                                break;
                            //DefaultValue
                            case "DefaultValue":
                                {
                                    _oneattribute.NameValue = "[" + itemattribute.Name + "(" + itemattribute.Value + ")]";
                                    _oneattribute.Name = itemattribute.Name;
                                    _oneattribute.Value = itemattribute.Value;
                                    _classprotry.DefaultValue = itemattribute.Value.Replace("\"", "");
                                }
                                break;
                            default:
                                {
                                    _oneattribute.NameValue = "[" + itemattribute.Name + "(" + itemattribute.Value + ")]";
                                    _oneattribute.Name = itemattribute.Name;
                                    _oneattribute.Value = itemattribute.Value;

                                    if (itemattribute.Name == "Display")
                                    {
                                        propertyCnName = itemattribute.Value.Replace("Name = ", "").Replace("\"", "");
                                    }
                                    if (itemattribute.Name == "Description")
                                    {
                                        _classprotry.PropertyDisplayStr = itemattribute.Value;
                                    }
                                }
                                break;
                        }


                        var expects = new List<string>() { "Comment", "Display", "Decription", "Index", "NotMapped", "Column", "DefaultValue" };
                        if (!expects.Contains(_oneattribute.Name))
                        {
                            classAttributes.Add(_oneattribute);
                        }
                    }
                    if (String.IsNullOrEmpty(_classprotry.PropertyDisplayStr))
                    {
                        var displayStr = property.DocComment.Replace("<doc>", "").Replace("</doc>", "").Replace("<summary>", "").Replace("</summary>", "").Replace("\r", "").Replace("\n", "").Trim();
                        _classprotry.PropertyDisplayStr = displayStr;
                    }
                    if (String.IsNullOrEmpty(propertyCnName))
                    {
                        if (!String.IsNullOrEmpty(_classprotry.PropertyDisplayStr))
                        {
                            propertyCnName = ToShortName(_classprotry.PropertyDisplayStr);
                        }
                    }
                    _classprotry.CnName = propertyCnName;
                    _classprotry.ClassAttributes = classAttributes;
                    classProperties.Add(_classprotry);
                }
            }
            model.ClassPropertys = classProperties;
            return model;
        }

        #region 生成后端
        /// <summary>
        /// 创建Dto类
        /// </summary>
        /// <param name="model"></param>
        /// <param name="name"></param>
        /// <param name="dtoFolder"></param>
        private void CreateDtoFile(TapClassModel model, ProjectItem dtoFolder, TemplateModel templatemodel)
        {
            if (!String.IsNullOrEmpty(templatemodel.dtobody))
            {
                AddFileToProjectItem(dtoFolder, buildFileContentByTemplate(model, templatemodel.dtobody), $"{model.Name}Dto.cs");
            }
            else
            {
                _AddItemDtoFile("apmodeldto", $"{model.Name}Dto.cs", model, dtoFolder);
            }

        }

        /// <summary>
        /// 创建只读仓储
        /// </summary>
        /// <param name="model"></param>
        /// <param name="name"></param>
        /// <param name="dtoFolder"></param>
        private void CreateReadRepositoryFile(TapClassModel model, string name, ProjectItem dtoFolder)
        {
            _AddItemDtoFile("apreadrepository", $"Read{name}Repository.cs", model, dtoFolder);
        }

        private void CreateHtmlFile(TapClassModel model, string name, ProjectItem dtoFolder)
        {
            //toLog("准备创建前端文件");
            _AddItemDtoFile("htmlindex", $"index.html", model, dtoFolder);
            _AddItemDtoFile("htmlview", $"view.html", model, dtoFolder);
        }

        //名称 模板名称 文件名称 动作执行
        private void _AddItemDtoFile(string tempname, string filename, TapClassModel model, ProjectItem dtoFolder)
        {
            //ThreadHelper.ThrowIfNotOnUIThread();
            //try
            //{
            //    //string fileName_GetsInput = $"{name}AddDto.cs";
            //    if (dtoFolder.ProjectItems.Item(filename) == null)
            //    {
            //        //string content_GetsInput = String.Empty;
            //        //判断是否是外置的文件模板
            //        var content_GetsInput = Engine.Razor.RunCompile(tempname, typeof(TapClassModel), model);
            //        if (!String.IsNullOrEmpty(content_GetsInput))
            //        {
            //            AddFileToProjectItem(dtoFolder, content_GetsInput.Replace("&quot;", ""), filename);
            //        }
            //        else
            //        {
            //            toLog(filename + "的模板为空，无法获取信息");
            //        }
            //    }
            //    else
            //    {
            //        toLog(filename + "已经存在无法继续写入");
            //    }
            //}
            //catch (Exception exl)
            //{
            //    toLog(exl.Message);
            //}
        }

        /// <summary>
        /// 生成appService文件
        /// </summary>
        /// <param name="model"></param>
        /// <param name="dtoFolder"></param>
        private void CreateServiceFile(TapClassModel model, ProjectItem dtoFolder, TemplateModel templatemodel)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var auto = dtoFolder.ProjectItems.Item($"{model.Name}AppService.cs");
            if (auto == null)
            {
                if (!String.IsNullOrEmpty(templatemodel.serverbody))
                {
                    AddFileToProjectItem(dtoFolder, buildFileContentByTemplate(model, templatemodel.serverbody), $"{model.Name}AppService.cs");
                }
                else
                {
                    toLog(Newtonsoft.Json.JsonConvert.SerializeObject(model));
                    _AddItemDtoFile("appservice", $"{model.Name}AppService.cs", model, dtoFolder);
                }
            }
            else
            {
                toLog("文件" + $"{model.Name}AppService.cs" + "已经存在，无法继续新增，需要新增请先删除");
            }
        }

        /// <summary>
        /// 添加DbSet到DbContext ReadDbContext
        /// </summary>
        /// <param name="topProject"></param>
        /// <param name="className"></param>
        private void SetDbSetToDbContext(ProjectItem entityFrameworkProject, string appplicationStr, string className, TapClassModel dtoModel)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var applicationNewFolder = entityFrameworkProject.SubProject.ProjectItems.Item("EntityFrameworkCore");
            if (applicationNewFolder != null)
            {
                if (applicationNewFolder.ProjectItems != null)
                {

                    SetDbSetToDbContext(applicationNewFolder.ProjectItems, appplicationStr, className, dtoModel);
                    //foreach (ProjectItem item in applicationNewFolder.ProjectItems)
                    //{
                    //    //标记他为读写分离模式
                    //    if (item.Name == ($"{appplicationStr}ReadDbContext.cs"))
                    //    {
                    //        dtoModel.IsWriteReadModel = true;
                    //    }

                    //    toLog("EFC.item:"+item.Name);

                    //    #region DbContext的模块
                    //    if (item.Name.EndsWith($"DbContext.cs"))
                    //    {
                    //        //customDtoMapperProjectItem = item;

                    //        if (item.FileCodeModel != null)
                    //        {
                    //            if (item.FileCodeModel.CodeElements != null)
                    //            {

                    //                CodeClass codeClass = GetSingleClass(item.FileCodeModel.CodeElements);

                    //                if (codeClass != null)
                    //                {
                    //                    //toLog("codeClass:" + codeClass.Name);
                    //                    var codeChilds = codeClass.Members;
                    //                    var fandDbset = false;
                    //                    foreach (CodeElement codeChild in codeChilds)
                    //                    {
                    //                        //toLog("codeChild:" + codeChild.Name);
                    //                        if (codeChild.Name == className)
                    //                        {
                    //                            fandDbset = true;
                    //                            break;
                    //                        }
                    //                    }
                    //                    if (!fandDbset)
                    //                    {
                    //                        if (codeClass.Kind == vsCMElement.vsCMElementClass && codeClass.Name.EndsWith("DbContext"))
                    //                        {
                    //                            var insertCode = codeClass.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
                    //                            insertCode.Insert("            public DbSet<" + className + "> " + className + " {get;set;}\r\n");
                    //                            insertCode.Insert("\r\n");
                    //                        }
                    //                        item.Save();
                    //                        continue;
                    //                    }
                    //                }
                    //                else
                    //                {
                    //                    var intefer = GetSingleInterface(item.FileCodeModel.CodeElements);
                    //                    if (intefer != null)
                    //                    {
                    //                        var codeChilds = intefer.Members;
                    //                        var fandDbset = false;
                    //                        foreach (CodeElement codeChild in codeChilds)
                    //                        {
                    //                            //toLog("codeChild:" + codeChild.Name);
                    //                            if (codeChild.Name == className)
                    //                            {
                    //                                fandDbset = true;
                    //                                break;
                    //                            }
                    //                        }
                    //                        if (!fandDbset)
                    //                        {
                    //                            if (intefer.Kind == vsCMElement.vsCMElementInterface && intefer.Name.EndsWith("DbContext"))
                    //                            {
                    //                                var insertCode = intefer.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
                    //                                insertCode.Insert("            public DbSet<" + className + "> " + className + " {get;set;}\r\n");
                    //                                insertCode.Insert("\r\n");
                    //                            }
                    //                            item.Save();
                    //                            continue;
                    //                        }
                    //                    }
                    //                }
                    //            }
                    //        }


                    //    }
                    //    #endregion

                    //    #region CreatingExtensions模块
                    //    if (item.Name.EndsWith("CreatingExtensions.cs"))
                    //    {


                    //        if (item.FileCodeModel != null)
                    //        {
                    //            if (item.FileCodeModel.CodeElements != null)
                    //            {

                    //                var boolhavewrite = false;
                    //                var filefullname = item.FileNames[0];
                    //                if (!String.IsNullOrEmpty(filefullname))
                    //                {

                    //                    if (System.IO.File.Exists(filefullname))
                    //                    {
                    //                        var filecontext = System.IO.File.ReadAllText(filefullname);
                    //                        if (!String.IsNullOrEmpty(filecontext))
                    //                        {
                    //                            if (filecontext.Contains($"**{className}**"))
                    //                            {
                    //                                boolhavewrite = true;
                    //                            }
                    //                        }
                    //                    }

                    //                }
                    //                if (!boolhavewrite)
                    //                {
                    //                    CodeClass codeClass = GetSingleClass(item.FileCodeModel.CodeElements);
                    //                    if (codeClass != null)
                    //                    {
                    //                        toLog("codeClass:" + codeClass.Name);
                    //                        var codeChilds = codeClass.Members;
                    //                        foreach (CodeElement codeChild in codeChilds)
                    //                        {
                    //                            toLog("codeChild:" + codeChild.Name + " type:" + codeChild.Kind);
                    //                            if (codeChild.Kind == vsCMElement.vsCMElementFunction && codeChild.Name.StartsWith("Configure"))
                    //                            {
                    //                                var insertCode = codeChild.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
                    //                                insertCode.Insert("//**" + className + "**\r\n");
                    //                                insertCode.Insert("builder.Entity<" + className + ">(b =>{\r\n");
                    //                                insertCode.Insert("b.ToTable(options.TablePrefix + \"" + className + "\", options.Schema);\r\n");
                    //                                insertCode.Insert("b.ConfigureByConvention();\r\n");
                    //                                insertCode.Insert("});\r\n");
                    //                                insertCode.Insert("\r\n");

                    //                            }
                    //                        }
                    //                        item.Save();
                    //                    }
                    //                }

                    //            }
                    //        }

                    //    }
                    //    #endregion
                    //}
                }
            }
        }

        private void SetDbSetToDbContext(ProjectItems _projectitems, string appplicationStr, string className, TapClassModel dtoModel)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            foreach (ProjectItem item in _projectitems)
            {
                //标记他为读写分离模式
                if (item.Name == ($"{appplicationStr}ReadDbContext.cs"))
                {
                    dtoModel.IsWriteReadModel = true;
                }
                //toLog("EFC.item:" + item.Name);

                #region DbContext的模块
                if (item.Name.EndsWith($"DbContext.cs"))
                {
                    //customDtoMapperProjectItem = item;

                    if (item.FileCodeModel != null)
                    {
                        if (item.FileCodeModel.CodeElements != null)
                        {

                            CodeClass codeClass = GetSingleClass(item.FileCodeModel.CodeElements);

                            if (codeClass != null)
                            {
                                //toLog("codeClass:" + codeClass.Name);
                                var codeChilds = codeClass.Members;
                                var fandDbset = false;
                                foreach (CodeElement codeChild in codeChilds)
                                {
                                    //toLog("codeChild:" + codeChild.Name);
                                    if (codeChild.Name == className)
                                    {
                                        fandDbset = true;
                                        break;
                                    }
                                }
                                if (!fandDbset)
                                {
                                    if (codeClass.Kind == vsCMElement.vsCMElementClass && codeClass.Name.EndsWith("DbContext"))
                                    {
                                        var insertCode = codeClass.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
                                        /// <summary>
                                        /// 
                                        /// </summary>
                                        insertCode.Insert("            /// <summary>\r\n");
                                        insertCode.Insert("            /// " + dtoModel.DisplayStr + "\r\n");
                                        insertCode.Insert("            /// </summary>\r\n");
                                        insertCode.Insert("            public DbSet<" + className + "> " + className + " {get;set;}\r\n");
                                        insertCode.Insert("\r\n");
                                    }
                                    item.Save();
                                    continue;
                                }
                            }
                            else
                            {
                                var intefer = GetSingleInterface(item.FileCodeModel.CodeElements);
                                if (intefer != null)
                                {
                                    var codeChilds = intefer.Members;
                                    var fandDbset = false;
                                    foreach (CodeElement codeChild in codeChilds)
                                    {
                                        //toLog("codeChild:" + codeChild.Name);
                                        if (codeChild.Name == className)
                                        {
                                            fandDbset = true;
                                            break;
                                        }
                                    }
                                    if (!fandDbset)
                                    {
                                        if (intefer.Kind == vsCMElement.vsCMElementInterface && intefer.Name.EndsWith("DbContext"))
                                        {
                                            var insertCode = intefer.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
                                            insertCode.Insert("            /// <summary>\r\n");
                                            insertCode.Insert("            /// " + dtoModel.DisplayStr + "\r\n");
                                            insertCode.Insert("            /// </summary>\r\n");
                                            insertCode.Insert("            public DbSet<" + className + "> " + className + " {get;set;}\r\n");
                                            insertCode.Insert("\r\n");
                                        }
                                        item.Save();
                                        continue;
                                    }
                                }
                            }
                        }
                    }


                }
                #endregion

                #region CreatingExtensions模块
                if (item.Name.EndsWith("CreatingExtensions.cs"))
                {
                    if (item.FileCodeModel != null)
                    {
                        if (item.FileCodeModel.CodeElements != null)
                        {
                            var boolhavewrite = false;
                            var filefullname = item.FileNames[0];
                            if (!String.IsNullOrEmpty(filefullname))
                            {
                                if (System.IO.File.Exists(filefullname))
                                {
                                    var filecontext = System.IO.File.ReadAllText(filefullname);
                                    if (!String.IsNullOrEmpty(filecontext))
                                    {
                                        if (filecontext.Contains($"**{className}**"))
                                        {
                                            boolhavewrite = true;
                                        }
                                    }
                                }
                            }
                            if (!boolhavewrite)
                            {
                                CodeClass codeClass = GetSingleClass(item.FileCodeModel.CodeElements);
                                if (codeClass != null)
                                {
                                    toLog("codeClass:" + codeClass.Name);
                                    var codeChilds = codeClass.Members;
                                    foreach (CodeElement codeChild in codeChilds)
                                    {
                                        toLog("codeChild:" + codeChild.Name + " type:" + codeChild.Kind);
                                        if (codeChild.Kind == vsCMElement.vsCMElementFunction && codeChild.Name.StartsWith("Configure"))
                                        {
                                            var insertCode = codeChild.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
                                            insertCode.Insert("//**" + className + "**\r\n");
                                            insertCode.Insert("builder.Entity<" + className + ">(b =>{\r\n");
                                            insertCode.Insert("b.ToTable(options.TablePrefix + \"" + className + "\", options.Schema);\r\n");
                                            insertCode.Insert("b.ConfigureByConvention();\r\n");
                                            insertCode.Insert("});\r\n");
                                            insertCode.Insert("\r\n");
                                        }
                                    }
                                    item.Save();
                                }
                            }

                        }
                    }

                }
                #endregion
            }
        }

        /// <summary>
        /// 编辑CustomDtoMapper.cs,添加映射
        /// </summary>
        /// <param name="applicationProject"></param>
        /// <param name="className"></param>
        /// <param name="classCnName"></param>
        private void SetMapper(ProjectItem applicationProject, string className, string classCnName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            SetMapper(applicationProject.SubProject.ProjectItems, className, classCnName);
        }


        /// <summary>
        /// 写入automapper信息对
        /// </summary>
        /// <param name="applicationProject"></param>
        /// <param name="className"></param>
        /// <param name="classCnName"></param>
        private void SetMapper(ProjectItems applicationProject, string className, string classCnName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            ProjectItem _automapprofile = null;
            foreach (ProjectItem item in applicationProject)
            {
                toLog(item.Name);
                if (item.Name.EndsWith("AutoMapperProfile.cs"))
                {
                    _automapprofile = item;
                    break;
                }
            }

            //  ProjectItem customDtoMapperProjectItem = _dte.Solution.FindProjectItem(applicationProject.FileName.Substring(0, applicationProject.FileName.LastIndexOf("\\")) + "\\AutoMapperProfile.cs");
            if (_automapprofile != null)
            {
                var boolhavewrite = false;
                var filefullname = _automapprofile.FileNames[0];
                if (!String.IsNullOrEmpty(filefullname))
                {
                    if (System.IO.File.Exists(filefullname))
                    {
                        var filecontext = System.IO.File.ReadAllText(filefullname);
                        if (!String.IsNullOrEmpty(filecontext))
                        {
                            if (filecontext.Contains($"#{className}#"))
                            {
                                boolhavewrite = true;
                            }
                        }
                    }
                }
                if (!boolhavewrite)
                {
                    //如果没有写入AutoMapper则写入
                    CodeClass codeClass = GetSingleClass(_automapprofile.FileCodeModel.CodeElements);
                    var codeChilds = codeClass.Members;
                    foreach (CodeElement codeChild in codeChilds)
                    {
                        if (codeChild.Kind == vsCMElement.vsCMElementFunction && codeChild.Name.EndsWith("AutoMapperProfile"))
                        {
                            var insertCode = codeChild.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
                            insertCode.Insert("            // #" + className + "#\r\n");
                            insertCode.Insert("            CreateMap<" + className + ", " + className + "ListDto>();\r\n");
                            insertCode.Insert("            CreateMap<" + className + ", " + className + "Dto>();\r\n");
                            insertCode.Insert("            CreateMap<" + className + ", " + className + "UpdateDto>();\r\n");
                            insertCode.Insert("            CreateMap<" + className + "UpdateDto, " + className + ">();\r\n");
                            insertCode.Insert("            CreateMap<" + className + "AddDto, " + className + ">();\r\n");
                            insertCode.Insert("\r\n");
                        }
                    }
                    _automapprofile.Save();
                }
            }
            else
            {
                toLog("没有找到AutoMapper的文件，无法写入AutoMapper的关系");
            }
        }

        #endregion

        #endregion

        #region 辅助方法
        /// <summary>
        /// 获取所有项目
        /// </summary>
        /// <param name="projectItems"></param>
        /// <returns></returns>
        private List<ProjectItem> GetProjects(ProjectItems projectItems)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var _list = new List<ProjectItem>();
            if (projectItems != null)
            {
                foreach (EnvDTE.ProjectItem item in projectItems)
                {
                    //toLog($"--:{item.Name}");
                    _list.Add(item);
                    if (item.SubProject != null)
                    {
                        foreach (EnvDTE.ProjectItem childItem in GetProjects(item.SubProject.ProjectItems))
                        {
                            //toLog($"---SubProject.ProjectItems:{childItem.Name}");
                            if (childItem.Kind == EnvDTE.Constants.vsProjectItemKindSolutionItems)
                            {
                                _list.Add(childItem);
                            }
                        }
                    }

                    if (item.ProjectItems != null)
                    {
                        foreach (EnvDTE.ProjectItem childItem in GetProjects(item.ProjectItems))
                        {
                            //toLog($"---ProjectItems:{childItem.Name}");
                            if (childItem.Kind == EnvDTE.Constants.vsProjectItemKindSolutionItems)
                            {
                                _list.Add(childItem);
                            }
                        }
                    }
                }
            }
            return _list;
        }


        /// <summary>
        /// 获取解决方案里面所有项目VSTHRD010
        /// </summary>
        /// <param name="solution"></paramGetSolutionProjects
        /// <returns></returns>
        private (List<ProjectItem>, List<Project>) GetSolutionProjects(Solution solution)
        {
            List<ProjectItem> _projectitems = new List<ProjectItem>();
            var projects = solution.Projects.OfType<Project>();
            foreach (var item in projects)
            {
                toLog("solution.subject " + item.Name + ":" + item.Kind);

                if (item.ParentProjectItem != null)
                {
                    toLog("parent project item .name :" + item.ParentProjectItem.Name);
                }


                var _isitem = item as ProjectItem;
                if (_isitem != null)
                {
                    toLog("解决方案的子项目是一个项目");
                    _projectitems.Add(_isitem);
                }

                if (item.ProjectItems != null)
                {
                    var _readlist = GetProjects(item.ProjectItems);
                    _projectitems.AddRange(_readlist);
                }
                else
                {
                    toLog($"{item.Name} not found projectitems!");
                }
            }

            return (_projectitems, projects.ToList());
        }

        /// <summary>
        /// 获取第一个类
        /// </summary>
        /// <param name="codeElements"></param>
        /// <returns></returns>
        private CodeClass GetSingleClass(CodeElements codeElements)
        {
            var elements = codeElements.Cast<CodeElement>().ToList();
            var result = elements.FirstOrDefault(codeElement => codeElement.Kind == vsCMElement.vsCMElementClass) as CodeClass;
            if (result != null)
            {
                return result;
            }
            foreach (var codeElement in elements)
            {
                result = GetSingleClass(codeElement.Children);
                if (result != null)
                {
                    return result;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取第一个接口
        /// </summary>
        /// <param name="codeElements"></param>
        /// <returns></returns>
        private CodeInterface GetSingleInterface(CodeElements codeElements)
        {
            var elements = codeElements.Cast<CodeElement>().ToList();
            var result = elements.FirstOrDefault(codeElement => codeElement.Kind == vsCMElement.vsCMElementInterface) as CodeInterface;
            if (result != null)
            {
                return result;
            }
            foreach (var codeElement in elements)
            {
                result = GetSingleInterface(codeElement.Children);
                if (result != null)
                {
                    return result;
                }
            }
            return null;
        }


        /// <summary>
        /// 读取enum 集合
        /// </summary>
        /// <param name="codeElements"></param>
        /// <param name="list"></param>
        private void _ReadEnumList(CodeElements codeElements, List<string> list)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var elements = codeElements.Cast<CodeElement>().ToList();

            foreach (var codeElement in elements)
            {
                if (codeElement.Kind == vsCMElement.vsCMElementEnum)
                {
                    list.Add(codeElement.Name);
                }
                else
                {
                    _ReadEnumList(codeElement.Children, list);
                }
            }
        }

        /// <summary>
        /// 读取class 集合
        /// </summary>
        /// <param name="codeElements"></param>
        /// <param name="list"></param>
        private void _ReadClassList(CodeElements codeElements, List<CodeClass> list)
        {
            var elements = codeElements.Cast<CodeElement>().ToList();


            //var result = elements.FirstOrDefault(codeElement => codeElement.Kind == vsCMElement.vsCMElementClass) as CodeClass;
            //if (result != null)
            //{
            //    yield return result;
            //}
            foreach (var codeElement in elements)
            {
                if (codeElement.Kind == vsCMElement.vsCMElementClass)
                {
                    list.Add(codeElement as CodeClass);
                }
                else
                {
                    _ReadClassList(codeElement.Children, list);
                }
            }
        }

        /// <summary>
        /// 获取当前所选文件去除项目目录后的文件夹结构
        /// </summary>
        /// <param name="selectProjectItem"></param>
        /// <returns></returns>
        private string GetSelectFileDirPath(Project topProject, ProjectItem selectProjectItem)
        {
            string dirPath = "";
            if (selectProjectItem != null)
            {
                //所选文件对应的路径
                string fileNames = selectProjectItem.FileNames[0];
                string selectedFullName = fileNames.Substring(0, fileNames.LastIndexOf('\\'));

                //所选文件所在的项目
                if (topProject != null)
                {
                    //项目目录
                    string projectFullName = topProject.FullName.Substring(0, topProject.FullName.LastIndexOf('\\'));

                    //当前所选文件去除项目目录后的文件夹结构
                    dirPath = selectedFullName.Replace(projectFullName, "");
                }
            }
            if (dirPath.Length > 0)
            {
                return dirPath.Substring(1);
            }
            else
            {
                return dirPath;
            }
        }

        /// <summary>
        /// 添加文件到项目中
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="content"></param>
        /// <param name="fileName"></param>
        private void AddFileToProjectItem(ProjectItem folder, string content, string fileName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            toLog($"准备创建文件{fileName}");
            string path = Path.GetTempPath();
            Directory.CreateDirectory(path);
            string file = Path.Combine(path, fileName);
            toLog($"创建临时文件{file}");
            File.WriteAllText(file, content, System.Text.Encoding.UTF8);
            try
            {
                folder.ProjectItems.AddFromFileCopy(file);
            }
            catch (Exception exl)
            {
                toLog("创建文件遇到异常!");
                toLog(exl.Message);
            }
            finally
            {
                File.Delete(file);
            }
        }

        /// <summary>
        /// 添加文件到指定目录
        /// </summary>
        /// <param name="directoryPathOrFullPath"></param>
        /// <param name="content"></param>
        /// <param name="fileName"></param>
        private void AddFileToDirectory(string directoryPathOrFullPath, string content, string fileName = "")
        {
            try
            {
                string file = string.IsNullOrEmpty(fileName) ? directoryPathOrFullPath : Path.Combine(directoryPathOrFullPath, fileName);
                File.WriteAllText(file, content, System.Text.Encoding.UTF8);
            }
            catch (Exception ex)
            {
                toLog("AddFileToDirectory" + ex.Message);
            }
        }

        /// <summary>
        /// 获取随后的一个名称
        /// </summary>
        /// <param name="ftrom"></param>
        /// <returns></returns>
        private string FilterOnlyName(string ftrom)
        {
            if (ftrom.IndexOf(".") > 0)
            {
                return ftrom.Substring(ftrom.LastIndexOf(".") + 1);
            }
            return ftrom;
        }

        /// <summary>
        /// 处理List的名称
        /// </summary>
        /// <param name="ftrom"></param>
        /// <returns></returns>
        private string FilterListOnlyName(string ftrom)
        {
            if (ftrom.IndexOf(".") > 0)
            {
                if (ftrom.IndexOf("<") > 0 && ftrom.IndexOf(">") > 0)
                {
                    //拿出主芯
                    var startindex = ftrom.LastIndexOf("<") + 1;
                    var endindex = ftrom.LastIndexOf(">");
                    var mainxin = ftrom.Substring(startindex, endindex - startindex);
                    if (mainxin.IndexOf(".") > 0)
                    {
                        return "List<" + FilterOnlyName(mainxin) + "Dto>";
                    }
                    else
                    {
                        return "List<" + FilterOnlyName(mainxin) + ">";
                    }
                }
                return "List<" + ftrom.Substring(ftrom.LastIndexOf(".") + 1) + "Dto>";
            }
            return ftrom;
        }
        #endregion


        #region 模板转文本相关代码

        /// <summary>
        /// 根据模板信息，生成对应的文件
        /// </summary>
        /// <param name="data"></param>
        /// <param name="templatestr"></param>
        /// <returns></returns>
        private static string buildFileContentByTemplate(TapClassModel data, string templatestr)
        {
            var template = DotLiquid.Template.Parse(templatestr);
            var buildBody = template.Render(DotLiquid.Hash.FromAnonymousObject(data));
            return buildBody;
        }

        #endregion


        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="str"></param>
        private static void toLog(string str)
        {
            WriteTextLog(str);
        }

        /// <summary>
        /// 删除日志
        /// </summary>
        private void _deletelog()
        {
            System.IO.File.Delete(@"C:\autocode\log\log.txt");
        }

        public static void WriteTextLog(string strMessage)
        {
            //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "=" + strMessage);

            if (Directory.Exists(@"C:\"))
            {
                string path = @"C:\autocode\log\";
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);

                string fileFullPath = path + "log.txt";
                System.Text.StringBuilder str = new StringBuilder();
                //str.Append("Time:    " + DateTime.Now.ToString() + "\r\n");
                str.Append(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":" + strMessage + "\r\n");
                //str.Append("-----------------------------------------------------------\r\n\r\n");
                StreamWriter sw;
                if (!File.Exists(fileFullPath))
                {
                    sw = File.CreateText(fileFullPath);
                }
                else
                {
                    sw = File.AppendText(fileFullPath);
                }
                sw.WriteLine(str.ToString());
                sw.Close();
            }


        }
    }
}
